package com.xxxtea.ws;

import com.xxxtea.common.Constants;
import com.xxxtea.dto.ChatUser;
import com.xxxtea.entity.User;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * WebSocket消息处理器
 * 
 * 该处理器负责管理WebSocket连接的生命周期，包括：
 * - 连接建立时的用户信息存储
 * - 连接关闭时的资源清理
 * - 维护在线用户列表和会话映射
 * 
 * 继承自TextWebSocketHandler，专门处理文本类型的WebSocket消息
 * 
 * @author badman
 * @since 1.0.0
 */
@Slf4j
@Getter
@Component
public class WebSocketHandler extends TextWebSocketHandler {
	
	/**
	 * 用户信息映射表
	 * key: 用户ID
	 * value: 聊天用户信息对象
	 */
	private final Map<Integer, ChatUser> userMap = new ConcurrentHashMap<>();
	
	/**
	 * WebSocket会话映射表
	 * key: 用户ID
	 * value: WebSocket会话对象
	 */
	private final Map<Integer, WebSocketSession> sessionMap = new ConcurrentHashMap<>();

	/**
	 * WebSocket连接建立后的处理
	 * 
	 * 当客户端成功建立WebSocket连接时调用此方法
	 * 将用户信息和会话对象存储到相应的映射表中
	 * 
	 * @param session WebSocket会话对象
	 */
	@Override
	public void afterConnectionEstablished(WebSocketSession session) {
		// 从会话属性中获取用户信息（在WebSocketAuthInterceptor中设置）
		User user = (User) session.getAttributes().get(Constants.WS_USER_KEY);
		
		// 将会话对象存储到会话映射表中
		sessionMap.put(user.getId(), session);
		
		// 将用户信息转换为ChatUser对象并存储到用户映射表中
		userMap.put(user.getId(), new ChatUser(user.getId(), user.getNickname(), user.getAvatar()));
		
		// 记录连接建立日志
		log.info("新的客户端建立连接: [{}@{}], 当前ws人数: {}", user.getId(), user.getNickname(), sessionMap.size());
	}

	/**
	 * WebSocket连接关闭后的处理
	 * 
	 * 当客户端断开WebSocket连接时调用此方法
	 * 清理相关的用户信息和会话对象
	 * 
	 * @param session WebSocket会话对象
	 * @param status 连接关闭状态
	 */
	@Override
	public void afterConnectionClosed(WebSocketSession session, @NonNull CloseStatus status) {
		// 从会话属性中获取用户信息
		User user = (User) session.getAttributes().get(Constants.WS_USER_KEY);
		
		// 从会话映射表中移除该用户的会话
		sessionMap.remove(user.getId());
		
		// 从用户映射表中移除该用户信息
		userMap.remove(user.getId());
		
		// 记录连接关闭日志
		log.info("客户端连接关闭: [{}@{}], 当前ws人数: {}", user.getId(), user.getNickname(), sessionMap.size());
	}

}